1. Descarga y preparación del corpus de datos¶
El objetivo de este primer notebook es realizar la carga del dataset para el posterior estudio y entrenamiento de modelos.
Importaciones¶
import librosa
import wave
import IPython.display as ipd
import numpy as np
import matplotlib.pyplot as plt
import datasets
import pandas as pd
from tqdm.auto import tqdm
from pprint import pprint
import os
1.1. Carga del conjunto de datos de HuggingFace¶
En esta sección vamos a presentar el principal conjunto de datos que utilizaremos para la realización de este proyecto, el conjunto de datos CCMUSIC.
Descarga en local del dataset desde HuggingFace¶
El principal dataset que utilizaremos, CCMUSIC, está disponible en HuggingFace. Al acceder a la página, nos encontramos con una tarjeta que nos proporciona detalles sobre el dataset y cómo obtener los datos.

Figura: CCMUSIC card en HuggingFace
Se nos indica la utilización del paquete datasets de HuggingFace, en concreto el método load_datasets, permitiendo la carga del conjunto de datos desde el repositorio de HuggingFace hacia una variable en nuestro código local.
ccmusic_corpus = datasets.load_dataset("ccmusic-database/music_genre", name="default",trust_remote_code=True)
Observación: la celda anterior tarda bastante tiempo en descargar, debido al elevado tamaño del dataset (aproximadamente 4 horas), por lo que se recomienda no ejecutarla a menos que cuente con tiempo suficiente. Alternativamente, puede proceder a visualizar las salidas del presente notebook ya ejecutadas.
Características generales del conjunto de datos¶
Estructura del conjunto de datos: campos y particiones
El conjunto de datos
ccmusic_corpuses unDatasetDict, un dataset con estructura de diccionario que contiene tres particiones (train,validationytest). Cuenta con un total de 1700 piezas ditribuidas en 1370 para entrenamiento, 171 para validación y 172 para test.Cada una de estas particiones es un objeto de tipo
Datasetque tiene los siguientes campos:audio: Este campo contiene información sobre el archivo de audio.path: La ruta al archivo de audio en el sistema de archivos.array: Un array NumPy que representa los datos del archivo de audio.sampling_rate: La frecuencia de muestreo del archivo de audio.
mel: Una imagen de las características mel-espectrograma. Es un objetoPIL.JpegImagePlugin.JpegImageFile.fst_level_label: Una etiqueta de clasificación de primer nivel.sec_level_label: Una etiqueta de clasificación de segundo nivel.thr_level_label: Una etiqueta de clasificación de tercer nivel.
Nosotros tenemos interés en
arrayyfst_level_label.
# Visualizamos la estructura de una entrada
print(ccmusic_corpus)
DatasetDict({
train: Dataset({
features: ['audio', 'mel', 'fst_level_label', 'sec_level_label', 'thr_level_label'],
num_rows: 1370
})
validation: Dataset({
features: ['audio', 'mel', 'fst_level_label', 'sec_level_label', 'thr_level_label'],
num_rows: 171
})
test: Dataset({
features: ['audio', 'mel', 'fst_level_label', 'sec_level_label', 'thr_level_label'],
num_rows: 172
})
})
# Visualizamos la estructura de una entrada del dataset
pprint(str(ccmusic_corpus['train'][0]))
("{'audio': {'path': "
"'C:\\\\Users\\\\Usuario\\\\.cache\\\\huggingface\\\\datasets\\\\downloads\\\\extracted\\\\9978c1aa27e41c465d1a0a120f523eae02b367b680fff33f401cee81e10d28c4\\\\audio\\\\2_non-classic\\\\11_rock\\\\21_Soft "
"Rock\\\\6573efb8158239c2015abeaea6bb8f65.mp3', 'array': array([0., 0., 0., "
"..., 0., 0., 0.]), 'sampling_rate': 22050}, 'mel': "
'<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=496x369 at '
"0x1FD640CE450>, 'fst_level_label': 1, 'sec_level_label': 8, "
"'thr_level_label': 14}")
Dataset orientado a clasificación
Se trata de un dataset orientado especialmente a tareas de clasificación. Las piezas musicales están etiquetadas de acuerdo con tres posibles jerarquías:
fst_level_label: separa las piezas de acuerdo a una clasificación binaria en música clásica y no clásica.sec_level_label: amplía las categorías, permitiendo distinguir hasta 9 géneros músicales dentro de estas 2 categorías principales.thr_level_label: amplía la jerarquía anterior, permitiendo disitinguir hasta 16 géneros musicales.
A continuación, se muestra un desglose de las categorías presentes en el dataset:
Classic
- Symphony
- Opera
- Solo
- Chamber
Non_classic
Pop
- Pop_vocal_ballad
- Adult_contemporary
- Teen_pop
Dance_and_house
- Contemporary_dance_pop
- Dance_pop
Indie
- Classic_indie_pop
- Chamber_cabaret_and_art_pop
Soul_or_r_and_b
Rock
- Adult_alternative_rock
- Uplifting_anthemic_rock
- Soft_rock
- Acoustic_pop
En este proyecto trabajaremos fundamentalmente con esta jerarquía de clasificación
fst_level_label.Vamos a visualizar, por ejemplo, la distribución de las categorías en train. Podemos observar que el dataset no se encuentra balanceado para ninguna de las jerarquías.
partition = "train"
print(f"---------Recuento de etiquetas en {partition} -------------------- ")
for column_name in ['fst_level_label', 'sec_level_label', 'thr_level_label']:
recuentos = pd.Series(ccmusic_corpus[partition][column_name]).value_counts().sort_index()
print(f"Jerarquía: {column_name}")
print(recuentos)
print()
---------Recuento de etiquetas en train -------------------- Jerarquía: fst_level_label 0 329 1 1041 Name: count, dtype: int64 Jerarquía: sec_level_label 0 84 1 85 2 81 3 79 4 258 5 153 6 164 7 167 8 299 Name: count, dtype: int64 Jerarquía: thr_level_label 0 84 1 85 2 81 3 79 4 89 5 84 6 85 7 76 8 77 9 83 10 81 11 167 12 72 13 76 14 78 15 73 Name: count, dtype: int64
Características de las señales de audio
Cada pieza está representada por una señal de audio mono, con una tasa de muestreo homogénea de 22050 Hz y una duración variable.
Vamos a visualizar un par de entradas del dataset de entrenamiento y mostraremos la reproducción del audio, la duración, la tasa de muestreo y su categoría.
index1 = 653
audio1 = ccmusic_corpus['train'][index1]['audio']['array']
sr1 = ccmusic_corpus['train'][index1]['audio']['sampling_rate']
label1 = ccmusic_corpus['train'][index1]['fst_level_label']
print("Audio escogido de train con índice", index1)
plt.figure(figsize=(5,2))
librosa.display.waveshow(audio1,sr=sr1,color="#f44",alpha=0.8)
plt.title(f"Señal de audio de entrenamiento con índice {index1}")
plt.show()
ipd.display(ipd.Audio(audio1, rate=sr1))
print(f"Dimensiones de la señal: {audio1.shape}")
print(f"Duración: {round(len(audio1)/sr1, 3)} segundos")
print(f"Tasa de muestreo: {sr1}")
print(f"Etiqueta (jerarquía 1): {"Classic" if label1 == "Classical" else "Non_classic"}")
Audio escogido de train con índice 653